//
//  ViewController.m
//  Mac_Obfunscation
//
//  Created by 7YAO on 2018/12/26.
//  Copyright © 2018年 7YAO. All rights reserved.
//

#import "ViewController.h"
#import "NSString+removeDot.h"

NSInteger kImageCount = 0;
NSInteger kfixImageCount = 0;
NSString *gSourceCodeDir;
NSInteger kPercent = 101;
NSInteger kLocalImageIndex = 0;
NSString *oldProjectName = @"";
NSString *gNewProjectName = @"";
NSString *gnewClassName = @"";
NSMutableDictionary *gspamName = nil;
NSString *gnewAPiPrefix = @"";

NSString *ignoreDirName = @"";



NSInteger kSpamCount = 0;
NSTextField *glabelText;
 NSString *gOutParameterName;
NSInteger kLocalImageIndex;
NSString *gOutParameterName;
@interface ViewController()
{

}


@property (weak) IBOutlet NSButton *obfunscationButton;
@property (weak) IBOutlet NSTextField *prefixTextField;
@property (weak) IBOutlet NSTextField *newprojectName;
@property (copy) NSString *filePath;

@property (copy) NSString *gOutParameterName;
@property (assign) NSInteger kLocalImageIndex;
@end


///递增重命名本地图片资源，xcode中的图片名称不变
NSString *randomString(NSInteger length) {
    //使用统一——背景名称
    NSString *imageName = [NSString stringWithFormat:@"insEyeImageSource_%03ld",(long)kLocalImageIndex];
    kLocalImageIndex +=1;
    return imageName;
}

void renameFile(NSString *oldPath, NSString *newPath) {
    NSError *error;
    [[NSFileManager defaultManager] moveItemAtPath:oldPath toPath:newPath error:&error];
    if (error) {
        printf("修改文件名称失败。\n  oldPath=%s\n  newPath=%s\n  ERROR:%s\n", oldPath.UTF8String, newPath.UTF8String, error.localizedDescription.UTF8String);
        abort();
    }
}


@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.obfunscationButton.enabled = false;
    [self.LabelText setEditable:false];
    
    gspamName = [NSMutableDictionary dictionary];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(chooseFolderchange) name:NSControlTextDidChangeNotification object:self.prefixTextField];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(chooseFolderchange) name:NSControlTextDidChangeNotification object:self.newprojectName];
}


- (void)setRepresentedObject:(id)representedObject {
    [super setRepresentedObject:representedObject];

    // Update the view, if already loaded.
}

///添加垃圾代码的策略
///为每一个.m文件添加一个方法，
#pragma mark 添加垃圾代码
void addSpamCodeFile(NSString *sourceCodeDir){
    NSFileManager *fm = [NSFileManager defaultManager];
    NSArray<NSString *> *files = [fm contentsOfDirectoryAtPath:sourceCodeDir error:nil];
    BOOL isDirectory;
     NSString *word_listpath =  [[NSBundle mainBundle]pathForResource:@"word_list" ofType:@"json"];
    NSData *data = [NSData dataWithContentsOfFile:word_listpath];
    NSArray *arrM = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
    
//    NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:word_listpath];
   
    for (NSString *filePath in files) {
        NSString *path = [sourceCodeDir stringByAppendingPathComponent:filePath];
        ///如果路径下的是文件夹，继续往下走,知道找到一个文件
        if ([fm fileExistsAtPath:path isDirectory:&isDirectory] && isDirectory) {
            addSpamCodeFile(path);
            continue;
        }
        NSString *fileName = filePath.lastPathComponent;
        NSMutableArray *tempspams = [NSMutableArray array];
        ///mm文件先不管
        if ([fileName hasSuffix:@".h"]) {
            NSString *hfileName = fileName.stringByDeletingPathExtension;
            NSString *mFileName = [hfileName stringByAppendingPathExtension:@"m"];
            if (![files containsObject:mFileName]) {
                continue;
            }
            gnewClassName = [mFileName substringToIndex:[mFileName rangeOfString:@"."].location];
            NSInteger spamCount =   20 + (arc4random() %30);
             NSMutableArray *marray = [NSMutableArray array];
            for (int i =0; i <spamCount;i++) {
                
                NSArray *apiList = @[@"sp_checkUserInfo",@"sp_upload",@"sp_getMediaData",@"sp_didGetInfoSuccess",@"sp_getUserFollowSuccess",@"sp_getLoginState",@"sp_checkNetWorking",@"sp_checkInfo",@"sp_getMediaFailed",@"sp_getUserName",@"sp_checkDefualtSetting",@"sp_didUserInfoFailed",@"sp_getUsersMostLiked",@"sp_getUsersMostLikedSuccess",@"sp_getUsersMostFollowerSuccess"];
                NSArray *logList = @[@"Get Info Success",@"Get Info Failed",@"Continue",@"Check your Network",@"Get User Succrss"];
                
                NSString *path = [[NSBundle mainBundle] pathForResource:@"insertAPIName" ofType:@"plist"];
                //            NSArray *logList = [NSArray arrayWithContentsOfFile:path];
                
                
                
                NSArray *param = @[@"string",@"mediaInfo",@"followCount",@"mediaCount",@"isLogin"];
                int listIndex = arc4random() % 15;
                int logIndex = arc4random() % 5;
                
                ///概率修改
                NSInteger k = arc4random()%100;
                if(k>kPercent){
                    continue;
                }
                NSString *api =  [NSString stringWithFormat:@"%@%@",apiList[listIndex],arrM[arc4random()%arrM.count]];
                
//                if(kSpamCount%4 == 0){
//                    NSString *api1 = [NSString stringWithFormat:@"[self %@:nil]",api];
//                    [tempspams addObject:api1];
//
//                }else
//                {
//                    NSString *api1 = [NSString stringWithFormat:@"[self %@]",api];
//                    [tempspams addObject:api1];
//                }
//
                creatApiToFile(sourceCodeDir, api , param[logIndex], logList[logIndex], [sourceCodeDir stringByAppendingPathComponent:filePath], YES,i,marray);
                
                creatApiToFile(sourceCodeDir,api, param[logIndex], logList[logIndex], filePath, NO,i,marray);
            
                kSpamCount += 1;
            }
            [gspamName setObject:marray forKey:gnewClassName];

        }
        
    }
    
}

#pragma mark 创建垃圾方法
void creatApiToFile(NSString *sourceCodeDir,NSString *apiName, NSString *paramName,NSString *logName,NSString *filePath, BOOL isHfile,int index1,NSMutableArray *marray){
    NSString *word_listpath =  [[NSBundle mainBundle]pathForResource:@"word_list" ofType:@"json"];
    NSData *data = [NSData dataWithContentsOfFile:word_listpath];
    if ([filePath containsString:@"Kra_fwtst"] || [filePath containsString:@"Kratos_fwtst"]) {
        
    }
    
    if(isHfile){
        NSError *error = nil;
        NSMutableString *fileContent = [NSMutableString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:&error];
        if([fileContent containsString:[NSString stringWithFormat:@"- (void)%@:(NSString * _Nullable)%@;\n", apiName,paramName]]){
            return;
        }
        //随机是否添加参数
        if(kSpamCount%4 == 0){
            NSString *s = @"@end";
            NSArray *endArray = [fileContent componentsSeparatedByString:s];
            NSMutableArray *arrayOfLocation=[NSMutableArray new];
            int d=0;
            for (int i=0; i<endArray.count-1; i++) {
                
                NSString *string=endArray[i];
                NSNumber *number=[NSNumber numberWithInt:d+=string.length];
                
                d+=s.length;
                [arrayOfLocation addObject:number];
                
            }
            
            if ( arrayOfLocation.count > 0)
            {
                NSNumber *number = arrayOfLocation[arrayOfLocation.count-1];
                NSInteger index = number.integerValue;
                [fileContent replaceCharactersInRange:NSMakeRange(index, 4) withString:@""];
                [fileContent appendFormat:@"- (void)%@:(NSString * _Nullable)%@;\n", apiName,paramName];
                [fileContent appendString:@"@end\n"];
            }
        }
        else{
            NSString *s = @"@end";
            NSArray *endArray = [fileContent componentsSeparatedByString:s];
            NSMutableArray *arrayOfLocation=[NSMutableArray new];
            int d=0;
            for (int i=0; i<endArray.count-1; i++) {
                
                NSString *string=endArray[i];
                NSNumber *number=[NSNumber numberWithInt:d+=string.length];
                d+=s.length;
                [arrayOfLocation addObject:number];
                
            }
            if (arrayOfLocation.count >1)
            {
                NSNumber *number = arrayOfLocation[arrayOfLocation.count-1];
                NSInteger index = number.integerValue;
                [fileContent replaceCharactersInRange:NSMakeRange(index, 4) withString:@""];
                [fileContent appendFormat:@"- (void)%@;\n", apiName];
                [fileContent appendString:@"@end\n"];
            }
         
        }
        [fileContent writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
    }
    else{
        NSString *sfileName = filePath.lastPathComponent.stringByDeletingPathExtension;
        NSString *mFileName = [sfileName stringByAppendingPathExtension:@"m"];
        NSString *mfilePath = [sourceCodeDir stringByAppendingPathComponent:mFileName];
        NSError *merror = nil;
        NSMutableString *mfileContent = [NSMutableString stringWithContentsOfFile:mfilePath encoding:NSUTF8StringEncoding error:&merror];
        if([mfileContent containsString:[NSString stringWithFormat:@"- (void)%@:(NSString * _Nullable)%@ {\n", apiName, paramName]]){
            return;
        }
        if(kSpamCount%4 == 0){
            NSString *s = @"@end";
            NSArray *endArray = [mfileContent componentsSeparatedByString:s];
            NSMutableArray *arrayOfLocation=[NSMutableArray new];
            int d=0;
            for (int i=0; i<endArray.count-1; i++) {
                
                NSString *string=endArray[i];
                NSNumber *number=[NSNumber numberWithInt:d+=string.length];
                
                d+=s.length;
                [arrayOfLocation addObject:number];
                
            }
            
            if (arrayOfLocation.count > 0)
            {
                
                NSNumber *number = arrayOfLocation[arrayOfLocation.count-1];
                NSInteger index = number.integerValue;
                [mfileContent replaceCharactersInRange:NSMakeRange(index, 4) withString:@""];
                if (index1 == 0) {
                    //在第一个垃圾方法签名添加//sourceCodeDir
                    [mfileContent appendFormat:@"//abcd\n"];
                     [mfileContent appendFormat:@"\n"];
                    [mfileContent appendFormat:@"- (void)%@:(NSString * _Nullable)%@ {\n", apiName, paramName];
                    
                    NSString *apwi =  [NSString stringWithFormat:@"%@",apiName];
                    NSString *api1 = [NSString stringWithFormat:@"[self %@:nil]",apwi];
                    [marray addObject:api1];
                }else
                {
                    [mfileContent appendFormat:@"- (void)%@:(NSString * _Nullable)%@ {\n", apiName, paramName];
                    NSString *apwi =  [NSString stringWithFormat:@"%@",apiName];
                    NSString *api1 = [NSString stringWithFormat:@"[self %@:nil]",apwi];
                    [marray addObject:api1];
                }
                
             
                
                
//                [mfileContent appendFormat:@"    NSLog(@\"%@\");\n", logName];

                [mfileContent appendString:@"}\n"];
                [mfileContent appendString:@"@end\n"];
     
//                NSString *apwi =  [NSString stringWithFormat:@"%@",apiName];
//                NSString *api1 = [NSString stringWithFormat:@"[self %@:nil]",apwi];
//                [marray addObject:api1];

                
            }
            
            
        }
        else{
            //不加参数
            NSString *s = @"@end";
            NSArray *endArray = [mfileContent componentsSeparatedByString:s];
            NSMutableArray *arrayOfLocation=[NSMutableArray new];
            int d=0;
            for (int i=0; i<endArray.count-1; i++) {
                
                NSString *string=endArray[i];
                NSNumber *number=[NSNumber numberWithInt:d+=string.length];
                
                d+=s.length;
                [arrayOfLocation addObject:number];
                
            }
            if (arrayOfLocation.count > 1)
            {
                NSNumber *number = arrayOfLocation[arrayOfLocation.count-1];
                NSInteger index = number.integerValue;
                [mfileContent replaceCharactersInRange:NSMakeRange(index, 4) withString:@""];
                [mfileContent appendFormat:@"- (void)%@ {\n", apiName];
//                [mfileContent appendFormat:@"    NSLog(@\"%@\");\n", logName];
                //            [mfileContent appendFormat:@"%@", logName];
                [mfileContent appendString:@"}\n"];
                [mfileContent appendString:@"@end\n"];
                
                NSString *apwi =  [NSString stringWithFormat:@"%@",apiName];
                NSString *api1 = [NSString stringWithFormat:@"[self %@]",apwi];
                [marray addObject:api1];
            
            }
          
        }
        [mfileContent writeToFile:[sourceCodeDir stringByAppendingPathComponent:mFileName] atomically:YES encoding:NSUTF8StringEncoding error:nil];
    }
}



void changePrefix(NSString *sourceCodeDir, NSArray<NSString *> *ignoreDirNames,NSString *oldName, NSString *newName){
    NSFileManager *fm = [NSFileManager defaultManager];
    
    // 遍历源代码文件 h 与 m 配对
    NSArray<NSString *> *files = [fm contentsOfDirectoryAtPath:sourceCodeDir error:nil];
    BOOL isDirectory;
    for (NSString *filePath in files) {
        NSString *path = [sourceCodeDir stringByAppendingPathComponent:filePath];
        if ([fm fileExistsAtPath:path isDirectory:&isDirectory] && isDirectory) {
            //            if (![ignoreDirNames containsObject:filePath]) {
            //                changePrefix(path, ignoreDirNames, oldName, newName);
            //            }
            changePrefix(path, ignoreDirNames, oldName, newName);
            continue;
        }
        
        NSString *fileName = filePath.lastPathComponent.stringByDeletingPathExtension;
        NSString *fileExtension = filePath.pathExtension;
        if ([fileExtension isEqualToString:@"h"]) {
            ///概率修改
            NSInteger k = arc4random()%100;
            if(k>kPercent){
                continue;
            }
            NSString *mFileName = [fileName stringByAppendingPathExtension:@"m"];
            NSString *mmFileName = [fileName stringByAppendingPathExtension:@"mm"];
            if ([files containsObject:mFileName]){
                NSString *hFilePath = [[sourceCodeDir stringByAppendingPathComponent:fileName] stringByAppendingPathExtension:@"h"];
                NSString *mFilePath = [[sourceCodeDir stringByAppendingPathComponent:fileName] stringByAppendingPathExtension:@"m"];
                NSError *error = nil;
                NSMutableString *fileContent = [NSMutableString stringWithContentsOfFile:mFilePath encoding:NSUTF8StringEncoding error:&error];
                if([fileContent containsString:oldName]){
                    [fileContent replaceOccurrencesOfString:oldName withString:newName options:NSCaseInsensitiveSearch range:NSMakeRange(0, fileContent.length)];
                    [fileContent writeToFile:mFilePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
                }
                NSMutableString *hfileConten = [NSMutableString stringWithContentsOfFile:hFilePath encoding:NSUTF8StringEncoding error:nil];
                if([hfileConten containsString:oldName]){
                    [hfileConten replaceOccurrencesOfString:oldName withString:newName options:NSCaseInsensitiveSearch range:NSMakeRange(0, hfileConten.length)];
                    [hfileConten writeToFile:hFilePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
                }
            }
            
            else if ([files containsObject:mmFileName]){
                NSString *hFilePath = [[sourceCodeDir stringByAppendingPathComponent:fileName] stringByAppendingPathExtension:@"h"];
                NSString *mFilePath = [[sourceCodeDir stringByAppendingPathComponent:fileName] stringByAppendingPathExtension:@"mm"];
                NSError *error = nil;
                NSMutableString *fileContent = [NSMutableString stringWithContentsOfFile:mFilePath encoding:NSUTF8StringEncoding error:&error];
                if([fileContent containsString:oldName]){
                    [fileContent replaceOccurrencesOfString:oldName withString:newName options:NSCaseInsensitiveSearch range:NSMakeRange(0, fileContent.length)];
                    [fileContent writeToFile:mFilePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
                }
                NSMutableString *hfileConten = [NSMutableString stringWithContentsOfFile:hFilePath encoding:NSUTF8StringEncoding error:nil];
                if([hfileConten containsString:oldName]){
                    [hfileConten replaceOccurrencesOfString:oldName withString:newName options:NSCaseInsensitiveSearch range:NSMakeRange(0, hfileConten.length)];
                    [hfileConten writeToFile:hFilePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
                }
            }
            else{
                NSString *hFilePath = [[sourceCodeDir stringByAppendingPathComponent:fileName] stringByAppendingPathExtension:@"h"];
                NSMutableString *hfileConten = [NSMutableString stringWithContentsOfFile:hFilePath encoding:NSUTF8StringEncoding error:nil];
                if([hfileConten containsString:oldName]){
                    [hfileConten replaceOccurrencesOfString:oldName withString:newName options:NSCaseInsensitiveSearch range:NSMakeRange(0, hfileConten.length)];
                    [hfileConten writeToFile:hFilePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
                }
            }
        }
    }
}



- (IBAction)ObfunscatonClick:(id)sender {
    
    
    
    [self verifyargument];
    [self proceed];
    
    
}


#pragma mark 当修改类前缀时，将引入到的地方也遍历修改
void replaceFileContend(NSString *sourceCodeDir,NSString *oldClassName,NSString *newClassName){
    NSFileManager *fm = [NSFileManager defaultManager];
    NSArray<NSString *> *files = [fm contentsOfDirectoryAtPath:sourceCodeDir error:nil];
    BOOL isDirectory;
    for (NSString *filePath in files) {
        NSString *path = [sourceCodeDir stringByAppendingPathComponent:filePath];
        ///如果路径下的是文件夹，继续往下走,知道找到一个文件
        if ([fm fileExistsAtPath:path isDirectory:&isDirectory] && isDirectory) {
            replaceFileContend(path,oldClassName,newClassName);
            continue;
        }
        NSString *fileName = filePath.lastPathComponent;
        ///mm文件先不管
        if ([fileName hasSuffix:@".h"] || [fileName hasSuffix:@".m"] || [fileName hasSuffix:@".mm"] || [fileName hasSuffix:@".pch"] || [fileName hasSuffix:@".swift"] || [fileName hasSuffix:@".xib"] || [fileName hasSuffix:@".storyboard"]) {
            NSError *error = nil;
            NSMutableString *fileContent = [NSMutableString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error];
            if (error) {
                printf("打开文件 %s 失败：%s\n", path.UTF8String, error.localizedDescription.UTF8String);
                abort();
            }
            if([fileContent containsString:oldClassName]){
                NSRange range = NSMakeRange(0, fileContent.length);
                [fileContent replaceOccurrencesOfString:oldClassName withString:newClassName options:NSCaseInsensitiveSearch range:range];
            }
        }
    }
}
#pragma mark 替换前缀方法名
BOOL regularReplacement(NSMutableString *originalString, NSString *regularExpression, NSString *newString) {
    __block BOOL isChanged = NO;
    BOOL isGroupNo1 = [newString isEqualToString:@"\\1"];
    NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:regularExpression options:NSRegularExpressionAnchorsMatchLines|NSRegularExpressionUseUnixLineSeparators error:nil];
    NSArray<NSTextCheckingResult *> *matches = [expression matchesInString:originalString options:0 range:NSMakeRange(0, originalString.length)];
    [matches enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(NSTextCheckingResult * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if (!isChanged) {
            isChanged = YES;
        }
        if (isGroupNo1) {
            NSString *withString = [originalString substringWithRange:[obj rangeAtIndex:1]];
            [originalString replaceCharactersInRange:obj.range withString:withString];
        } else {
            [originalString replaceCharactersInRange:obj.range withString:newString];
        }
    }];
    return isChanged;
}


#pragma mark - 删除注释
    void deleteComments(NSString *directory) {
        NSFileManager *fm = [NSFileManager defaultManager];
        NSArray<NSString *> *files = [fm contentsOfDirectoryAtPath:directory error:nil];
        BOOL isDirectory;
        for (NSString *fileName in files) {
            NSString *filePath = [directory stringByAppendingPathComponent:fileName];
            if ([fm fileExistsAtPath:filePath isDirectory:&isDirectory] && isDirectory) {
                deleteComments(filePath);
                continue;
            }
            
            if (![fileName hasSuffix:@".h"] && ![fileName hasSuffix:@".m"] && ![fileName hasSuffix:@".swift"]) continue;
            NSMutableString *fileContent = [NSMutableString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
            regularReplacement(fileContent, @"([^:/])//.*",             @"\\1");
            regularReplacement(fileContent, @"^//.*",                   @"");
            regularReplacement(fileContent, @"/\\*{1,2}[\\s\\S]*?\\*/", @"");
            regularReplacement(fileContent, @"^\\s*\\n",                @"");
            [fileContent writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
        }
    }

#pragma mark - 修改类名前缀
#pragma mark - 查找以XX结尾的文件
NSString* findSuffix(NSString *directory ,NSString *Suffix) {
    NSFileManager *fm = [NSFileManager defaultManager];
    NSArray<NSString *> *files = [fm contentsOfDirectoryAtPath:directory error:nil];
    BOOL isDirectory;
    for (NSString *fileName in files) {
        NSString *filePath = [directory stringByAppendingPathComponent:fileName];
        if ([fm fileExistsAtPath:filePath isDirectory:&isDirectory] && isDirectory) {
            findSuffix(filePath , Suffix);
            continue;
        }
        if (![fileName hasSuffix:Suffix]) continue;
        return filePath;
    }
    return nil;
}
#pragma mark - 修改类名前缀----
void modifyFilesClassName(NSString *sourceCodeDir, NSString *oldClassName, NSString *newClassName) {
    // 文件内容 Const > DDConst (h,m,swift,xib,storyboard)
    NSFileManager *fm = [NSFileManager defaultManager];
    NSArray<NSString *> *files = [fm contentsOfDirectoryAtPath:sourceCodeDir error:nil];
    BOOL isDirectory;
    for (NSString *filePath in files) {
        NSString *path = [sourceCodeDir stringByAppendingPathComponent:filePath];
        ///如果路径下的是文件夹，继续往下走，知道找到一个文件
        if ([fm fileExistsAtPath:path isDirectory:&isDirectory] && isDirectory) {
            modifyFilesClassName(path, oldClassName, newClassName);
            continue;
        }
//
        NSString *fileName = filePath.lastPathComponent;
        if ([fileName hasSuffix:@".h"] || [fileName hasSuffix:@".m"] || [fileName hasSuffix:@".mm"] || [fileName hasSuffix:@".pch"] || [fileName hasSuffix:@".swift"] || [fileName hasSuffix:@".xib"] || [fileName hasSuffix:@".storyboard"]) {
            NSError *error = nil;
            NSMutableString *fileContent = [NSMutableString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error];
            if (error) {
                printf("打开文件 %s 失败：%s\n", path.UTF8String, error.localizedDescription.UTF8String);
                abort();
            }
            
            NSString *regularExpression = [NSString stringWithFormat:@"\\b%@\\b", oldClassName];
            BOOL isChanged = regularReplacement(fileContent, regularExpression, newClassName);
            if (!isChanged) continue;
            error = nil;
            [fileContent writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:&error];
            if (error) {
                printf("保存文件 %s 失败：%s\n", path.UTF8String, error.localizedDescription.UTF8String);
                abort();
            }
            replaceFileContend(gSourceCodeDir, oldClassName, newClassName);
        }
    }
}
#pragma mark   改Podfile 中的工程名
void replacePodfileContent(NSString *filePath, NSString *oldString, NSString *newString) {
    NSMutableString *fileContent = [NSMutableString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
    
    NSString *regularExpression = [NSString stringWithFormat:@"target +'%@", oldString];
    NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:regularExpression options:0 error:nil];
    NSArray<NSTextCheckingResult *> *matches = [expression matchesInString:fileContent options:0 range:NSMakeRange(0, fileContent.length)];
    [matches enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(NSTextCheckingResult * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        [fileContent replaceCharactersInRange:obj.range withString:[NSString stringWithFormat:@"target '%@", newString]];
    }];
    
    regularExpression = [NSString stringWithFormat:@"project +'%@.", oldString];
    expression = [NSRegularExpression regularExpressionWithPattern:regularExpression options:0 error:nil];
    matches = [expression matchesInString:fileContent options:0 range:NSMakeRange(0, fileContent.length)];
    [matches enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(NSTextCheckingResult * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        [fileContent replaceCharactersInRange:obj.range withString:[NSString stringWithFormat:@"project '%@.", newString]];
    }];
    
    [fileContent writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
}

#pragma mark resetBridgingHeader内容
void resetBridgingHeaderFileName(NSString *projectPbxprojFilePath, NSString *oldName, NSString *newName) {
    NSString *rootPath = projectPbxprojFilePath.stringByDeletingLastPathComponent.stringByDeletingLastPathComponent;
    NSMutableString *fileContent = [NSMutableString stringWithContentsOfFile:projectPbxprojFilePath encoding:NSUTF8StringEncoding error:nil];
    NSString *regularExpression = @"SWIFT_OBJC_BRIDGING_HEADER = \"?([^\";]+)";
    NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:regularExpression options:0 error:nil];
    NSArray<NSTextCheckingResult *> *matches = [expression matchesInString:fileContent options:0 range:NSMakeRange(0, fileContent.length)];
    [matches enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(NSTextCheckingResult * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        NSString *entitlementsPath = [fileContent substringWithRange:[obj rangeAtIndex:1]];
        NSString *entitlementsName = entitlementsPath.lastPathComponent.stringByDeletingPathExtension;
        if (![entitlementsName isEqualToString:oldName]) return;
        entitlementsPath = [rootPath stringByAppendingPathComponent:entitlementsPath];
        if (![[NSFileManager defaultManager] fileExistsAtPath:entitlementsPath]) return;
        NSString *newPath = [entitlementsPath.stringByDeletingLastPathComponent stringByAppendingPathComponent:[newName stringByAppendingPathExtension:@"h"]];
        renameFile(entitlementsPath, newPath);
    }];
}

#pragma mark -修改Entitlements授权文件
void resetEntitlementsFileName(NSString *projectPbxprojFilePath, NSString *oldName, NSString *newName) {
    NSString *rootPath = projectPbxprojFilePath.stringByDeletingLastPathComponent.stringByDeletingLastPathComponent;
    NSMutableString *fileContent = [NSMutableString stringWithContentsOfFile:projectPbxprojFilePath encoding:NSUTF8StringEncoding error:nil];
    
    NSString *regularExpression = @"CODE_SIGN_ENTITLEMENTS = \"?([^\";]+)";
    NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:regularExpression options:0 error:nil];
    NSArray<NSTextCheckingResult *> *matches = [expression matchesInString:fileContent options:0 range:NSMakeRange(0, fileContent.length)];
    [matches enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(NSTextCheckingResult * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        NSString *entitlementsPath = [fileContent substringWithRange:[obj rangeAtIndex:1]];
        NSString *entitlementsName = entitlementsPath.lastPathComponent.stringByDeletingPathExtension;
        if (![entitlementsName isEqualToString:oldName]) return;
        entitlementsPath = [rootPath stringByAppendingPathComponent:entitlementsPath];
        if (![[NSFileManager defaultManager] fileExistsAtPath:entitlementsPath]) return;
        NSString *newPath = [entitlementsPath.stringByDeletingLastPathComponent stringByAppendingPathComponent:[newName stringByAppendingPathExtension:@"entitlements"]];
        renameFile(entitlementsPath, newPath);
    }];
}
#pragma mark -修改替换项目文件内容
void replaceProjectFileContent(NSString *filePath, NSString *oldString, NSString *newString) {
    NSMutableString *fileContent = [NSMutableString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
    
    NSString *regularExpression = [NSString stringWithFormat:@"\\b%@\\b", oldString];
    NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:regularExpression options:0 error:nil];
    NSArray<NSTextCheckingResult *> *matches = [expression matchesInString:fileContent options:0 range:NSMakeRange(0, fileContent.length)];
    [matches enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(NSTextCheckingResult * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        [fileContent replaceCharactersInRange:obj.range withString:newString];
    }];
    
    [fileContent writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
}

#pragma mark 修改工程名字

void modifyProjectName(NSString *projectDir, NSString *oldName, NSString *newName) {
    NSString *sourceCodeDirPath = [projectDir stringByAppendingPathComponent:oldName];
    NSString *xcodeprojFilePath = [sourceCodeDirPath stringByAppendingPathExtension:@"xcodeproj"];
    NSString *xcworkspaceFilePath = [sourceCodeDirPath stringByAppendingPathExtension:@"xcworkspace"];
    
    NSFileManager *fm = [NSFileManager defaultManager];
    BOOL isDirectory;
    
    // old-Swift.h > new-Swift.h
    modifyFilesClassName(projectDir, [oldName stringByAppendingString:@"-Swift.h"], [newName stringByAppendingString:@"-Swift.h"]);
    
    // 改 Podfile 中的工程名
    NSString *podfilePath = [projectDir stringByAppendingPathComponent:@"Podfile"];
    if ([fm fileExistsAtPath:podfilePath isDirectory:&isDirectory] && !isDirectory) {
        replacePodfileContent(podfilePath, oldName, newName);
    }
    
    // 改工程文件内容
    if ([fm fileExistsAtPath:xcodeprojFilePath isDirectory:&isDirectory] && isDirectory) {
        // 替换 project.pbxproj 文件内容
        NSString *projectPbxprojFilePath = [xcodeprojFilePath stringByAppendingPathComponent:@"project.pbxproj"];
        if ([fm fileExistsAtPath:projectPbxprojFilePath]) {
            resetBridgingHeaderFileName(projectPbxprojFilePath, [oldName stringByAppendingString:@"-Bridging-Header"], [newName stringByAppendingString:@"-Bridging-Header"]);
            resetEntitlementsFileName(projectPbxprojFilePath, oldName, newName);
            replaceProjectFileContent(projectPbxprojFilePath, oldName, newName);
        }
        // 替换 project.xcworkspace/contents.xcworkspacedata 文件内容
        NSString *contentsXcworkspacedataFilePath = [xcodeprojFilePath stringByAppendingPathComponent:@"project.xcworkspace/contents.xcworkspacedata"];
        if ([fm fileExistsAtPath:contentsXcworkspacedataFilePath]) {
            replaceProjectFileContent(contentsXcworkspacedataFilePath, oldName, newName);
        }
        // xcuserdata 本地用户文件
        NSString *xcuserdataFilePath = [xcodeprojFilePath stringByAppendingPathComponent:@"xcuserdata"];
        if ([fm fileExistsAtPath:xcuserdataFilePath]) {
            [fm removeItemAtPath:xcuserdataFilePath error:nil];
        }
        
        
        NSString * path =  findSuffix(xcodeprojFilePath, @".xcscheme");
        
        // 改名工程文件
        renameFile(xcodeprojFilePath, [[projectDir stringByAppendingPathComponent:newName] stringByAppendingPathExtension:@"xcodeproj"]);
        
        
     
        
        
    }
    
    // 改工程组文件内容
    if ([fm fileExistsAtPath:xcworkspaceFilePath isDirectory:&isDirectory] && isDirectory) {
        // 替换 contents.xcworkspacedata 文件内容
        NSString *contentsXcworkspacedataFilePath = [xcworkspaceFilePath stringByAppendingPathComponent:@"contents.xcworkspacedata"];
        if ([fm fileExistsAtPath:contentsXcworkspacedataFilePath]) {
            replaceProjectFileContent(contentsXcworkspacedataFilePath, oldName, newName);
        }
        // xcuserdata 本地用户文件
        NSString *xcuserdataFilePath = [xcworkspaceFilePath stringByAppendingPathComponent:@"xcuserdata"];
        if ([fm fileExistsAtPath:xcuserdataFilePath]) {
            [fm removeItemAtPath:xcuserdataFilePath error:nil];
        }
        // 改名工程文件
        renameFile(xcworkspaceFilePath, [[projectDir stringByAppendingPathComponent:newName] stringByAppendingPathExtension:@"xcworkspace"]);
    }
    
    // 改源代码文件夹名称
    if ([fm fileExistsAtPath:sourceCodeDirPath isDirectory:&isDirectory] && isDirectory) {
        renameFile(sourceCodeDirPath, [projectDir stringByAppendingPathComponent:newName]);
    }
}




- (BOOL)verifyargument
{
    
    if (self.filePath.length < 1)
    {
        NSLog(@"没有选择项目路径");
        return false;
    }
    return YES;
}

#pragma mark  入口
- (void)proceed
{

    
    gSourceCodeDir = self.filePath;
    self.LabelText.stringValue = @"fffffff";
    NSArray *arguments = [[NSProcessInfo processInfo] arguments];
    NSMutableArray *arguments2 =  [NSMutableArray arrayWithArray:arguments];
    arguments2[1] = self.filePath;
    //modifyProjectName 参数
    arguments2[2] = @"-modifyProjectName";
    if (oldProjectName.length <= 1)
    {
        NSAlert *alert = [[NSAlert alloc] init];
        [alert setMessageText:@"没有找到.xcodeproj文件"];
        [alert beginSheetModalForWindow:self.view.window completionHandler:^(NSModalResponse returnCode) {
            
        }];
    }
    arguments2[3] = [NSString stringWithFormat:@"%@>%@",oldProjectName,self.newprojectName.stringValue];
    arguments2[4] = @"-spamCodeOut";
    arguments2[5] = @"ignoreDirNames";
    arguments2[6] = ignoreDirName;
    arguments2[7] = @"-handleXcassets";
    arguments2[8] = @"-chageAPIPrefix";
    arguments2[9] = [NSString stringWithFormat:@"%@>%@",self.prefixTextField.stringValue,self.newprojectName.stringValue];
    arguments2[10] = @"-modifyAPIName";
    arguments2[11] = @"-modifyClassNamePrefix";
    arguments2[12] =[NSString stringWithFormat:@"%@/%@.xcodeproj",self.filePath,oldProjectName];
    arguments2[13] =[NSString stringWithFormat:@"%@>%@",self.prefixTextField.stringValue,self.newprojectName.stringValue];
    BOOL isDirectory = NO;
    NSString *outDirString = nil;
    NSArray<NSString *> *ignoreDirNames = nil;
    BOOL needHandleXcassets = NO;
    BOOL needDeleteComments = NO;
    BOOL needModifyAPIName = NO;
    NSString *oldProjectName = nil;
    NSString *newProjectName = nil;
    NSString *projectFilePath = nil;
    NSString *oldClassNamePrefix = nil;
    NSString *newClassNamePrefix = nil;
    NSString *oldAPiPrefix = nil;
    NSString *newAPiPrefix = nil;

    NSFileManager *fm = [NSFileManager defaultManager];
    for (NSInteger i = 1; i < arguments2.count; i++)
    {
        NSString *argument = arguments2[i];
        if (i == 1) {
            gSourceCodeDir = argument;
            if (![fm fileExistsAtPath:gSourceCodeDir isDirectory:&isDirectory]) {
                printf("%s不存在\n", [gSourceCodeDir UTF8String]);
                return ;
            }
            if (!isDirectory) {
                printf("%s不是目录\n", [gSourceCodeDir UTF8String]);
                return;
            }
            continue;
        }
        ///修改图片名字
        if ([argument isEqualToString:@"-handleXcassets"]) {
            needHandleXcassets = YES;
            continue;
        }
        if ([argument isEqualToString:@"-deleteComments"]) {
            needDeleteComments = YES;
            continue;
        }
        if ([argument isEqualToString:@"-modifyProjectName"]) {
            NSString *string = arguments2[++i];
            NSArray<NSString *> *names = [string componentsSeparatedByString:@">"];
            if (names.count < 2) {
                printf("修改工程名参数错误。参数示例：CCApp>DDApp，传入参数：%s\n", string.UTF8String);
                return;
            }
            oldProjectName = names[0];
            newProjectName = names[1];
            if (oldProjectName.length <= 0 || newProjectName.length <= 0) {
                printf("修改工程名参数错误。参数示例：CCApp>DDApp，传入参数：%s\n", string.UTF8String);
                return;
            }
            continue;
        }
        if ([argument isEqualToString:@"-modifyClassNamePrefix"]) {
            NSString *string = arguments2[++i];
            projectFilePath = [string stringByAppendingPathComponent:@"project.pbxproj"];
            if (![fm fileExistsAtPath:string isDirectory:&isDirectory] || !isDirectory
                || ![fm fileExistsAtPath:projectFilePath isDirectory:&isDirectory] || isDirectory) {
                printf("-modifyClassNamePrefix 修改类名前缀的工程文件参数错误。%s", string.UTF8String);
                return;
            }

            string = arguments2[++i];
            NSArray<NSString *> *names = [string componentsSeparatedByString:@">"];
            if (names.count < 2) {
                printf("修改类名前缀参数错误。参数示例：CC>DD，传入参数：%s\n", string.UTF8String);
                return;
            }
            
            oldClassNamePrefix = names[0];
            newClassNamePrefix = names[1];
            if (oldClassNamePrefix.length <= 0 || newClassNamePrefix.length <= 0) {
                printf("修改类名前缀参数错误。参数示例：CC>DD，传入参数：%s\n", string.UTF8String);
                return;
            }
            continue;
        }
        
        
        if ([argument isEqualToString:@"-spamCodeOut"]) {
            outDirString = @"新增垃圾代码";
            //                outDirString = arguments[++i];
            //                if ([fm fileExistsAtPath:outDirString isDirectory:&isDirectory]) {
            //                    if (!isDirectory) {
            //                        printf("%s 已存在但不是文件夹，需要传入一个输出文件夹目录\n", [outDirString UTF8String]);
            //                        return 1;
            //                    }
            //                } else {
            //                    NSError *error = nil;
            //                    if (![fm createDirectoryAtPath:outDirString withIntermediateDirectories:YES attributes:nil error:&error]) {
            //                        printf("创建输出目录失败，请确认 -spamCodeOut 之后接的是一个“输出文件夹目录”参数，错误信息如下：\n传入的输出文件夹目录：%s\n%s\n", [outDirString UTF8String], [error.localizedDescription UTF8String]);
            //                        return 1;
            //                    }
            //                }
            //
            //                i++;
            //                if (i < arguments.count) {
            //                    gOutParameterName = arguments[i];
            //                    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"[a-zA-Z]+" options:0 error:nil];
            //                    if ([regex numberOfMatchesInString:gOutParameterName options:0 range:NSMakeRange(0, gOutParameterName.length)] <= 0) {
            //                        printf("缺少垃圾代码参数名，或参数名\"%s\"不合法(需要字母开头)\n", [gOutParameterName UTF8String]);
            //                        return 1;
            //                    }
            //                } else {
            //                    printf("缺少垃圾代码参数名，参数名需要根在输出目录后面\n");
            //                    return 1;
            //                }
            //
            continue;
        }
        if ([argument isEqualToString:@"-ignoreDirNames"]) {
            ignoreDirNames = [arguments2[++i] componentsSeparatedByString:@","];
            continue;
        }
        if ([argument isEqualToString:@"-chageAPIPrefix"]){
            NSString *string = arguments2[++i];
            NSArray<NSString *> *names = [string componentsSeparatedByString:@">"];
            if (names.count < 2) {
                printf("-chageAPIPrefix 修改方法名前缀参数错误。参数示例：gd_>ie_，传入参数：%s\n", string.UTF8String);
                return;
            }
            if ([names[0] containsString:@"_"])
            {
                oldAPiPrefix =  names[0];
            }else
            {
                oldAPiPrefix =  [names[0] stringByAppendingString:@"_"];
            }
            
            newAPiPrefix = [names[1] stringByAppendingString:@"_"];
            if (oldAPiPrefix.length <= 0 || newAPiPrefix.length <= 0 || ![oldAPiPrefix containsString:@"_"] || ![newAPiPrefix containsString:@"_"]) {
                printf("修改方法名前缀参数错误。参数示例：gd_>ie_，传入参数：%s\n", string.UTF8String);
                return;
            }
            continue;
        }
        if([argument isEqualToString:@"-modifyAPIName"]){
            needModifyAPIName = YES;
            continue;
        }
    }
    
    
    if (needHandleXcassets) {
        @autoreleasepool {
            handleXcassetsFiles(gSourceCodeDir);
            printf("正在修改图片。。。");
        }
        printf("修改 Xcassets 中的图片名称完成,一共有%ld个图片文件，修改了%ld个\n",(long)kImageCount,(long)kfixImageCount);
    }
    
    
    if (needModifyAPIName){
        printf("正在删除sp_的垃圾代码\n");
        @autoreleasepool {
            deleteAllSpamCode(gSourceCodeDir,@"sp_");
        }
        printf("删除sp_的垃圾代码完成\n");
        
    }
    if (needDeleteComments) {
        @autoreleasepool {
            deleteComments(gSourceCodeDir);
        }
        printf("删除注释和空行完成\n");
    }
    
    //修改类名前缀
    if (oldClassNamePrefix && newClassNamePrefix) {
        printf("开始修改类名前缀...\n");
        @autoreleasepool {
            // 打开工程文件
            NSError *error = nil;
            NSMutableString *projectContent = [NSMutableString stringWithContentsOfFile:projectFilePath encoding:NSUTF8StringEncoding error:&error];
            if (error) {
                printf("打开工程文件 %s 失败：%s\n", projectFilePath.UTF8String, error.localizedDescription.UTF8String);
                return;
            }
            
            modifyClassNamePrefix(projectContent, gSourceCodeDir, ignoreDirNames, oldClassNamePrefix, newClassNamePrefix,self);

            [projectContent writeToFile:projectFilePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
        }
        
        printf("修改类名前缀完成\n");
    }
    
    
    
    if (oldProjectName && newProjectName) {
        printf("正在修改工程名\n");
        @autoreleasepool {
            gNewProjectName = newProjectName;
//            NSString *dir = gSourceCodeDir.stringByDeletingLastPathComponent;
            NSString *dir = gSourceCodeDir;
            modifyProjectName(dir, oldProjectName, newProjectName);
        }
        printf("修改工程名完成\n");
    }

    
    
    if (outDirString) {
        @autoreleasepool {
            printf("正在生成垃圾代码\n");
            addSpamCodeFile(gSourceCodeDir);
            
        }
        //            recursiveDirectory(gSourceCodeDir, ignoreDirNames, ^(NSString *mFilePath) {
        //
        //            }, ^(NSString *swiftFilePath) {
        //                @autoreleasepool {
        //                    generateSwiftSpamCodeFile(outDirString, swiftFilePath);
        //                }
        //            });
        printf("生成垃圾代码完成\n");
    }
    
    
    if(newAPiPrefix &&oldAPiPrefix){
        @autoreleasepool {
            printf("正在替换方法名前缀\n");
            changePrefix(gSourceCodeDir, ignoreDirNames, oldAPiPrefix, newAPiPrefix);
        }
        printf("替换方法名前缀完成\n");
    }
    @autoreleasepool {
        gnewAPiPrefix = newAPiPrefix;
        bcfobf(gSourceCodeDir, oldAPiPrefix, newAPiPrefix);
    }
    
    printf("执行完毕");
    
}
# pragma mark 控制流混淆

BOOL bcfobf(NSString *sourceCodeDir, NSString *oldClassName, NSString *newClassName) {
    
    NSFileManager *fm = [NSFileManager defaultManager];
    NSArray<NSString *> *files = [fm contentsOfDirectoryAtPath:sourceCodeDir error:nil];
    BOOL isDirectory;
    for (NSString *filePath in files) {
        NSString *path = [sourceCodeDir stringByAppendingPathComponent:filePath];
        ///如果路径下的是文件夹，继续往下走，知道找到一个文件
        if ([fm fileExistsAtPath:path isDirectory:&isDirectory] && isDirectory) {
            
            bcfobf(path, oldClassName, newClassName);
            continue;
        }
        
        NSString *fileName = filePath.lastPathComponent;
        if ( [fileName hasSuffix:@".m"] || [fileName hasSuffix:@".mm"] ) {
            NSError *error = nil;
            NSMutableString *fileContent = [NSMutableString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error];
            if (error) {
                printf("打开文件 %s 失败：%s\n", path.UTF8String, error.localizedDescription.UTF8String);
                abort();
            }
          
            
            
            gnewClassName = [fileName substringToIndex:[fileName rangeOfString:@"."].location];
//            NSString *regularExpression = [NSString stringWithFormat:@"\\b%@\\b", newClassName];
            NSString *regularExpression = [NSString stringWithFormat:@"[-]\\s?\\(.*\\)%@.*\\n?\\{", newClassName];

//            BOOL isChanged = regularReplacement(fileContent, regularExpression, newClassName);
            
            insertStrCount = 0;
            bcfobf1(fileContent, regularExpression,path);


                if (error) {
                    printf("保存文件 %s 失败：%s\n", path.UTF8String, error.localizedDescription.UTF8String);
                    abort();
                }
            
          
            replaceFileContend(gSourceCodeDir, oldClassName, newClassName);
        }
    }
    
    
    return  false;
}
 long insertStrCount = 0;
#pragma mark 查找 {}
NSString* CharInNSString(NSString *string ,NSString *c,NSString *d)
{
    NSInteger x = 0;
    
@autoreleasepool {
    for (int i = 0; i < [string length]; i++) {
        NSString *str  = [string substringWithRange:NSMakeRange(i, 1)];
        
        if ([str isEqualToString:c])
        {
            x++;
        }

        if ([str isEqualToString:d])
        {
            x--;
        }
        
        if (x == -1  && [str  isEqualToString:d] )
        {
            return  [string substringToIndex:i + 1];
        }
        
//        if ((char)[string characterAtIndex:i] == c ) {
//
//            x++;
//        }
//        if ((char)[string characterAtIndex:i] == d ) {
//            x--;
//        }
//        if (x == -1  && (char)[string characterAtIndex:i] == d )
//        {
//            return  [string substringToIndex:i + 1];
//        }
    }
    
}
    
    return @"";
}

NSArray *fwe(NSString * originalString,NSString *regularExpression)
{
    NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:regularExpression options:NSRegularExpressionAnchorsMatchLines|NSRegularExpressionUseUnixLineSeparators error:nil];
    NSArray<NSTextCheckingResult *> *matches = [expression matchesInString:originalString options:0 range:NSMakeRange(0, originalString.length)];
    [matches enumerateObjectsUsingBlock:^(NSTextCheckingResult * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        
    }];
    return matches;
    
}
#pragma 随机调用垃圾方法
void  bcfobf1(NSMutableString * originalString,NSString *regularExpression,NSString *file)
{
    if (insertStrCount < 100) {
        NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:regularExpression options:NSRegularExpressionAnchorsMatchLines|NSRegularExpressionUseUnixLineSeparators error:nil];
        NSArray<NSTextCheckingResult *> *matches = [expression matchesInString:originalString options:0 range:NSMakeRange(0, originalString.length)];
        if (insertStrCount == matches.count) return;
        for (int i = (int)insertStrCount ; i<matches.count; i++)
        {
            NSTextCheckingResult *result = matches[i];
            NSString * fw = [originalString substringFromIndex:result.range.location + result.range.length];
            NSString *ff =  CharInNSString(fw, @"{", @"}");
            NSArray<NSTextCheckingResult*> *arrayStr1  = fwe(ff, @"\\[.*\\];");
            if (arrayStr1.count == 0)
            {
                return;
            }
            NSSet *set =[NSSet setWithArray:arrayStr1];
            long location = 0;
            NSTextCheckingResult *resul =  [set anyObject];
            NSLog(@"==  %@ ==%@  ", NSStringFromRange(resul.range),[ff substringWithRange:resul.range]);
            NSArray *tempArray = gspamName[gnewClassName];
            for (int j = 0; j <=arc4random() % 10; j++)
            {
                NSString *inserString = [NSString stringWithFormat:@"\n%@;\n",tempArray[arc4random() %tempArray.count]];
                [originalString insertString:inserString atIndex:  result.range.location + result.range.length+(resul.range.location+resul.range.length + 1 + location)];
                NSError *error = nil;
                [originalString writeToFile:file atomically:YES encoding:NSUTF8StringEncoding error:&error];
                if (error) {
                    printf("保存文件 %s 失败：%s\n", file.UTF8String, error.localizedDescription.UTF8String);
                    abort();
                }
            }
            insertStrCount++;
            bcfobf1(originalString, regularExpression, file);
        }
        
    }
  
}

//获取这个字符串中的所有xxx的所在的index
NSMutableArray * getRangeStr(NSString *text, NSString *findText)
{
    NSMutableArray *arrayRanges = [NSMutableArray arrayWithCapacity:20];
    if (findText == nil && [findText isEqualToString:@""]) {
        return nil;
    }
    NSRange rang = [text rangeOfString:findText]; //获取第一次出现的range
    if (rang.location != NSNotFound && rang.length != 0) {
        [arrayRanges addObject:[NSNumber numberWithInteger:rang.location+ findText.length]];//将第一次的加入到数组中
        NSRange rang1 = {0,0};
        NSInteger location = 0;
        NSInteger length = 0;
        for (int i = 0;; i++)
        {
            if (0 == i) {//去掉这个xxx
                location = rang.location + rang.length;
                length = text.length - rang.location - rang.length;
                rang1 = NSMakeRange(location, length);
            }else
            {
                location = rang1.location + rang1.length;
                length = text.length - rang1.location - rang1.length;
                rang1 = NSMakeRange(location, length);
            }
            //在一个range范围内查找另一个字符串的range
            rang1 = [text rangeOfString:findText options:NSCaseInsensitiveSearch range:rang1];
            if (rang1.location == NSNotFound && rang1.length == 0) {
                break;
            }else//添加符合条件的location进数组
                [arrayRanges addObject:[NSNumber numberWithInteger:rang1.location+findText.length]];
        }
        return arrayRanges;
    }
    return nil;
}




NSMutableArray * calculateSubStringCount(NSString *content ,NSString *tab) {
    int location = 0;
    NSMutableArray *locationArr = [NSMutableArray new];
    NSRange range = [content rangeOfString:tab];
    if (range.location == NSNotFound){
        return locationArr;
    }
    NSString * subStr = content;
    while (range.location != NSNotFound) {
        if (location == 0) {
            location += range.location;
        } else {
            location += range.location + tab.length;
        }
        NSNumber *number = [NSNumber numberWithUnsignedInteger:location];
        [locationArr addObject:number];
        subStr = [subStr substringFromIndex:range.location + range.length];
        range = [subStr rangeOfString:tab];
    }
    return locationArr;
}

#pragma mark 替换类的前缀
void modifyClassNamePrefix(NSMutableString *projectContent, NSString *sourceCodeDir, NSArray<NSString *> *ignoreDirNames, NSString *oldName, NSString *newName,ViewController *vc) {
    NSFileManager *fm = [NSFileManager defaultManager];
    
    // 遍历源代码文件 h 与 m 配对，swift
    NSArray<NSString *> *files = [fm contentsOfDirectoryAtPath:sourceCodeDir error:nil];
    BOOL isDirectory;
    
    for (NSString *filePath in files) {
        NSString *path = [sourceCodeDir stringByAppendingPathComponent:filePath];
        dispatch_async(dispatch_get_main_queue(), ^{
            [vc.LabelText setStringValue:[NSString stringWithFormat:@"正在分析%@",path]];
        });
        if ([fm fileExistsAtPath:path isDirectory:&isDirectory] && isDirectory) {
            if (![ignoreDirNames containsObject:filePath]) {
                modifyClassNamePrefix(projectContent, path, ignoreDirNames, oldName, newName,vc);
            }
            continue;
        }
        ///概率修改
        NSInteger k = arc4random()%100;
        if(k>kPercent){
            continue;
        }
        NSString *fileName = filePath.lastPathComponent.stringByDeletingPathExtension;
        NSString *fileExtension = filePath.pathExtension;
        NSString *newClassName;
        if ([fileName hasPrefix:oldName]) {
            newClassName = [newName stringByAppendingString:[fileName substringFromIndex:oldName.length]];
        } else {
            //            newClassName = [newName stringByAppendingString:fileName];
            //不包含前缀的不加新前缀
            newClassName = fileName;
        }
        
        // 文件名 Const.ext > DDConst.ext
        if ([fileExtension isEqualToString:@"h"]) {
            NSString *mFileName = [fileName stringByAppendingPathExtension:@"m"];
            NSString *mmFileName = [fileName stringByAppendingPathExtension:@"mm"];
            if ([files containsObject:mFileName]) {
                NSString *oldFilePath = [[sourceCodeDir stringByAppendingPathComponent:fileName] stringByAppendingPathExtension:@"h"];
                NSString *newFilePath = [[sourceCodeDir stringByAppendingPathComponent:newClassName] stringByAppendingPathExtension:@"h"];
                renameFile(oldFilePath, newFilePath);
                oldFilePath = [[sourceCodeDir stringByAppendingPathComponent:fileName] stringByAppendingPathExtension:@"m"];
                newFilePath = [[sourceCodeDir stringByAppendingPathComponent:newClassName] stringByAppendingPathExtension:@"m"];
                renameFile(oldFilePath, newFilePath);
                oldFilePath = [[sourceCodeDir stringByAppendingPathComponent:fileName] stringByAppendingPathExtension:@"xib"];
                if ([fm fileExistsAtPath:oldFilePath]) {
                    newFilePath = [[sourceCodeDir stringByAppendingPathComponent:newClassName] stringByAppendingPathExtension:@"xib"];
                    renameFile(oldFilePath, newFilePath);
                }
                
                @autoreleasepool {
                    modifyFilesClassName(gSourceCodeDir, fileName, newClassName);
                }
            }
            else if([files containsObject:mmFileName]){
                NSString *oldFilePath = [[sourceCodeDir stringByAppendingPathComponent:fileName] stringByAppendingPathExtension:@"h"];
                NSString *newFilePath = [[sourceCodeDir stringByAppendingPathComponent:newClassName] stringByAppendingPathExtension:@"h"];
                renameFile(oldFilePath, newFilePath);
                oldFilePath = [[sourceCodeDir stringByAppendingPathComponent:fileName] stringByAppendingPathExtension:@"mm"];
                newFilePath = [[sourceCodeDir stringByAppendingPathComponent:newClassName] stringByAppendingPathExtension:@"mm"];
                renameFile(oldFilePath, newFilePath);
                oldFilePath = [[sourceCodeDir stringByAppendingPathComponent:fileName] stringByAppendingPathExtension:@"xib"];
                if ([fm fileExistsAtPath:oldFilePath]) {
                    newFilePath = [[sourceCodeDir stringByAppendingPathComponent:newClassName] stringByAppendingPathExtension:@"xib"];
                    renameFile(oldFilePath, newFilePath);
                }
                
                @autoreleasepool {
                    modifyFilesClassName(gSourceCodeDir, fileName, newClassName);
                }
            }
            else {
                NSString *oldFilePath = [[sourceCodeDir stringByAppendingPathComponent:fileName] stringByAppendingPathExtension:@"h"];
                NSString *newFilePath = [[sourceCodeDir stringByAppendingPathComponent:newClassName] stringByAppendingPathExtension:@"h"];
                renameFile(oldFilePath, newFilePath);
                @autoreleasepool {
                    modifyFilesClassName(gSourceCodeDir, fileName, newClassName);
                }
                //                continue;
            }
        } else if ([fileExtension isEqualToString:@"swift"]) {
            NSString *oldFilePath = [[sourceCodeDir stringByAppendingPathComponent:fileName] stringByAppendingPathExtension:@"swift"];
            NSString *newFilePath = [[sourceCodeDir stringByAppendingPathComponent:newClassName] stringByAppendingPathExtension:@"swift"];
            renameFile(oldFilePath, newFilePath);
            oldFilePath = [[sourceCodeDir stringByAppendingPathComponent:fileName] stringByAppendingPathExtension:@"xib"];
            if ([fm fileExistsAtPath:oldFilePath]) {
                newFilePath = [[sourceCodeDir stringByAppendingPathComponent:newClassName] stringByAppendingPathExtension:@"xib"];
                renameFile(oldFilePath, newFilePath);
            }
            
            @autoreleasepool {
                modifyFilesClassName(gSourceCodeDir, fileName.stringByDeletingPathExtension, newClassName);
            }
        } else {
            continue;
        }
        
        // 修改工程文件中的文件名
        NSString *regularExpression = [NSString stringWithFormat:@"\\b%@\\b", fileName];
        regularReplacement(projectContent, regularExpression, newClassName);
    }
}


    
#pragma mark 处理XcodeAsset
void handleXcassetsFiles(NSString *directory) {
    NSFileManager *fm = [NSFileManager defaultManager];
    NSArray<NSString *> *files = [fm contentsOfDirectoryAtPath:directory error:nil];
    BOOL isDirectory;
    for (NSString *fileName in files) {
        NSString *filePath = [directory stringByAppendingPathComponent:fileName];
        if ([fm fileExistsAtPath:filePath isDirectory:&isDirectory] && isDirectory) {
            handleXcassetsFiles(filePath);
            continue;
        }
        if (![fileName isEqualToString:@"Contents.json"]) continue;
        NSString *contentsDirectoryName = filePath.stringByDeletingLastPathComponent.lastPathComponent;
        if (![contentsDirectoryName hasSuffix:@".imageset"]) continue;
        
        NSString *fileContent = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
        if (!fileContent) continue;
        
        NSMutableArray<NSString *> *processedImageFileNameArray = @[].mutableCopy;
        static NSString * const regexStr = @"\"filename\" *: *\"(.*)?\"";
        NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:regexStr options:NSRegularExpressionUseUnicodeWordBoundaries error:nil];
        NSArray<NSTextCheckingResult *> *matches = [expression matchesInString:fileContent options:0 range:NSMakeRange(0, fileContent.length)];
        while (matches.count > 0) {
            NSInteger i = 0;
            NSString *imageFileName = nil;
            do {
                if (i >= matches.count) {
                    i = -1;
                    break;
                }
                imageFileName = [fileContent substringWithRange:[matches[i] rangeAtIndex:1]];
                i++;
            } while ([processedImageFileNameArray containsObject:imageFileName]);
            if (i < 0) break;
            
            NSString *imageFilePath = [filePath.stringByDeletingLastPathComponent stringByAppendingPathComponent:imageFileName];
            ///先
            NSInteger k = arc4random()%100;
            //概率混淆
            kImageCount += 1;
            if(k>kPercent){
                continue;
            }
            kfixImageCount +=1;
            if ([fm fileExistsAtPath:imageFilePath]) {
                NSString *newImageFileName = [randomString(10) stringByAppendingPathExtension:imageFileName.pathExtension];
                NSString *newImageFilePath = [filePath.stringByDeletingLastPathComponent stringByAppendingPathComponent:newImageFileName];
                while ([fm fileExistsAtPath:newImageFileName]) {
                    newImageFileName = [randomString(10) stringByAppendingPathExtension:imageFileName.pathExtension];
                    newImageFilePath = [filePath.stringByDeletingLastPathComponent stringByAppendingPathComponent:newImageFileName];
                }
                
                renameFile(imageFilePath, newImageFilePath);
                
                fileContent = [fileContent stringByReplacingOccurrencesOfString:[NSString stringWithFormat:@"\"%@\"", imageFileName]
                                                                     withString:[NSString stringWithFormat:@"\"%@\"", newImageFileName]];
                [fileContent writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
                
                [processedImageFileNameArray addObject:newImageFileName];
            } else {
                [processedImageFileNameArray addObject:imageFileName];
            }
            
            matches = [expression matchesInString:fileContent options:0 range:NSMakeRange(0, fileContent.length)];
        }
    }
}



- (void)dealloc
{
    [[NSNotificationCenter defaultCenter]removeObserver:self];
}


#pragma mark 删除所有垃圾代码以"sp_"开头,前缀可自定义，只要不与本身方法重合就可以
void deleteAllSpamCode(NSString *sourceCodeDir,NSString *prefix)
{
    NSFileManager *fm = [NSFileManager defaultManager];
    NSArray<NSString *> *files = [fm contentsOfDirectoryAtPath:sourceCodeDir error:nil];
    BOOL isDirectory;
    for (NSString *filePath in files) {
        NSString *path = [sourceCodeDir stringByAppendingPathComponent:filePath];
        ///如果路径下的是文件夹，继续往下走，知道找到一个文件
        if ([fm fileExistsAtPath:path isDirectory:&isDirectory] && isDirectory) {
            deleteAllSpamCode(path, prefix);
            continue;
        }
        
        if (![filePath hasSuffix:@".h"] && ![filePath hasSuffix:@".m"] && ![filePath hasSuffix:@".swift"]) continue;
        NSMutableString *fileContent = [NSMutableString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];

        if ([filePath hasSuffix:@".m"])
        {
//            regularReplacement(fileContent, @"^- \\(void\\)sp_.*\\}",         @"");
            //匹配以sp开头的垃圾方法
            NSString *regularExpression = @"^- \\(void\\)sp_.*\\}";
          __block  NSMutableString *originalString = fileContent;
                NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:regularExpression options:NSRegularExpressionAnchorsMatchLines|NSRegularExpressionDotMatchesLineSeparators error:nil];
                NSArray<NSTextCheckingResult *> *matches = [expression matchesInString:originalString options: 0  range:NSMakeRange(0, originalString.length)];
                [matches enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(NSTextCheckingResult * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                    
                    [originalString replaceCharactersInRange:obj.range withString:@""];
                
                }];
            
            
             //匹配以sp开头的垃圾方法调用
            NSString *regularExpression1 = @"\\[self sp_[a-zA-Z0-9:?]*\\];";
            NSRegularExpression *expression1 = [NSRegularExpression regularExpressionWithPattern:regularExpression1 options:NSRegularExpressionAnchorsMatchLines|NSRegularExpressionDotMatchesLineSeparators error:nil];
            NSArray<NSTextCheckingResult *> *matches1 = [expression1 matchesInString:originalString options: 0  range:NSMakeRange(0, originalString.length)];
            [matches1 enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(NSTextCheckingResult * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                
                [originalString replaceCharactersInRange:obj.range withString:@""];
                
            }];
            
        }
        if ([filePath hasSuffix:@".h"])
        {
            regularReplacement(fileContent, @"- \\(void\\)sp_.*;",                @"");
        }
        
        
        
        [fileContent writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:nil];
        
        
    }
    
        
}
    
- (IBAction)chooseFoloderClick:(NSButton *)sender
{
    
    NSOpenPanel *openPanel = [NSOpenPanel openPanel];
    openPanel.prompt = @"选择";
    openPanel.canChooseDirectories = YES;
    openPanel.canChooseFiles = NO;
    [openPanel beginSheetModalForWindow:self.view.window completionHandler:^(NSModalResponse result) {
        if (result != NSModalResponseOK) return;
        self.filePath =   openPanel.URLs.firstObject.path;
        ///获取项目的后缀
        NSFileManager *fm = [NSFileManager defaultManager];
        NSArray<NSString *> *files = [fm contentsOfDirectoryAtPath: self.filePath error:nil];
        [files enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            if ([[obj lastPathComponent] containsString:@".xcodeproj"] ) {
                oldProjectName = [obj stringByReplacingOccurrencesOfString:@".xcodeproj" withString:@""];
            }
        }];
        [self chooseFolderchange];
    }];
}

- (void)chooseFolderchange
{
    self.obfunscationButton.enabled = (self.filePath.length > 0) && self.prefixTextField.stringValue.removeDot.length > 0 && self.newprojectName.stringValue.length > 0;
}

@end
